package com.starhub.utils;

import org.apache.poi.xwpf.usermodel.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

public class HtmlToDocxConverter {

    private static final Pattern SELF_CLOSING_TAGS = Pattern.compile(
            "<(br|hr|img|input|meta|link|base|area|col|command|embed|keygen|param|source|track|wbr)([^>]*?)(?<!/)>",
            Pattern.CASE_INSENSITIVE);

    public static XWPFDocument convertHtmlToDocx(String html) {
        // 1. 预处理HTML
        String processedHtml = preprocessHtml(html);

        // 2. 创建XWPFDocument
        XWPFDocument doc = new XWPFDocument();

        // 3. 使用JSoup解析HTML
        Document document = Jsoup.parse(processedHtml);

        // 4. 创建样式映射
        Map<String, XWPFStyle> styles = new HashMap<>();

        // 5. 处理文档内容
        processNode(document.body(), doc, null, styles);

        return doc;
    }

    private static String preprocessHtml(String html) {
        // 1. 处理自闭合标签
        String processed = SELF_CLOSING_TAGS.matcher(html).replaceAll("<$1$2/>");

        // 2. 确保HTML有根元素
        if (!processed.trim().startsWith("<html")) {
            processed = "<html><body>" + processed + "</body></html>";
        }

        // 3. 处理特殊字符
        processed = processed.replace("&nbsp;", " ")
                .replace("&lt;", "<")
                .replace("&gt;", ">")
                .replace("&amp;", "&")
                .replace("&quot;", "\"")
                .replace("&apos;", "'");

        return processed;
    }

    private static boolean isBlockElement(String tag) {
        return tag.matches("p|div|h[1-6]|li|td|th|ul|ol|table|tr");
    }

    private static void processNode(Node node, XWPFDocument doc, XWPFParagraph currentParagraph,
            Map<String, XWPFStyle> styles) {
        if (node instanceof TextNode) {
            String text = ((TextNode) node).text();
            if (!text.trim().isEmpty() && currentParagraph != null) {
                XWPFRun run = currentParagraph.createRun();
                run.setText(text);
                applyStyles(run, node.parent(), styles);
            }
        } else if (node instanceof Element element) {
            String tag = element.tagName().toLowerCase();
            if (isBlockElement(tag)) {
                XWPFParagraph paragraph = doc.createParagraph();
                applyParagraphStyles(paragraph, element, styles);
                for (Node child : element.childNodes()) {
                    processNode(child, doc, paragraph, styles);
                }
            } else if (tag.equals("br")) {
                if (currentParagraph != null) {
                    currentParagraph.createRun().addBreak();
                }
            } else {
                // 行内元素
                for (Node child : element.childNodes()) {
                    processNode(child, doc, currentParagraph, styles);
                }
            }
        }
    }

    // 递归收集所有父级 style 和标签
    private static class StyleTag {
        String style;
        String tag;

        StyleTag(String style, String tag) {
            this.style = style;
            this.tag = tag;
        }
    }

    private static List<StyleTag> collectStyleTags(Node node) {
        List<StyleTag> list = new ArrayList<>();
        Node current = node;
        while (current instanceof Element) {
            Element el = (Element) current;
            list.add(0, new StyleTag(el.attr("style"), el.tagName().toLowerCase()));
            current = current.parent();
        }
        return list;
    }

    private static void applyStyles(XWPFRun run, Node node, Map<String, XWPFStyle> styles) {
        if (node instanceof Element) {
            List<StyleTag> styleTags = collectStyleTags(node);
            // 合并所有 style
            StringBuilder mergedStyle = new StringBuilder();
            for (StyleTag st : styleTags) {
                if (st.style != null && !st.style.trim().isEmpty()) {
                    mergedStyle.append(st.style).append(";");
                }
            }
            String style = mergedStyle.toString();

            if (!style.trim().isEmpty()) {
                // 处理字体
                String fontFamily = extractStyleValue(style, "font-family");
                if (fontFamily != null) {
                    run.setFontFamily(fontFamily);
                }

                // 处理字号
                String fontSize = extractStyleValue(style, "font-size");
                if (fontSize != null) {
                    try {
                        int size = Integer.parseInt(fontSize.replace("pt", "").trim());
                        run.setFontSize(size);
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                    }
                }

                // 处理粗体
                String fontWeight = extractStyleValue(style, "font-weight");
                if (fontWeight != null && (fontWeight.equals("bold") || fontWeight.equals("700"))) {
                    run.setBold(true);
                }

                // 处理斜体
                String fontStyle = extractStyleValue(style, "font-style");
                if (fontStyle != null && fontStyle.equals("italic")) {
                    run.setItalic(true);
                }

                // 处理下划线
                String textDecoration = extractStyleValue(style, "text-decoration");
                if (textDecoration != null && textDecoration.contains("underline")) {
                    run.setUnderline(UnderlinePatterns.SINGLE);
                }

                // 处理颜色
                String color = extractStyleValue(style, "color");
                if (color != null) {
                    String hexColor = convertToHexColor(color);
                    if (hexColor != null) {
                        run.setColor(hexColor);
                    }
                }

                // 处理背景色
                String bgColor = extractStyleValue(style, "background-color");
                if (bgColor != null) {
                    String hexColor = convertToHexColor(bgColor);
                    if (hexColor != null) {
                        run.setTextHighlightColor(hexColor);
                    }
                }
            }
            // 叠加所有标签特性
            for (StyleTag st : styleTags) {
                switch (st.tag) {
                    case "s":
                    case "del":
                    case "strike":
                        run.setStrikeThrough(true);
                        break;
                    case "u":
                        run.setUnderline(UnderlinePatterns.SINGLE);
                        break;
                    case "sub":
                        run.setSubscript(VerticalAlign.SUBSCRIPT);
                        break;
                    case "sup":
                        run.setSubscript(VerticalAlign.SUPERSCRIPT);
                        break;
                    case "mark":
                        run.setTextHighlightColor("yellow");
                        break;
                    case "strong":
                    case "b":
                        run.setBold(true);
                        break;
                    case "em":
                    case "i":
                        run.setItalic(true);
                        break;
                    default:
                        // 其他未知标签不做特殊处理
                        break;
                }
            }
        }
    }

    private static String convertToHexColor(String color) {
        if (color == null)
            return null;

        // 移除所有空格
        color = color.replaceAll("\\s+", "");

        // 处理十六进制颜色
        if (color.startsWith("#")) {
            return color.substring(1);
        }

        // 处理RGB颜色
        if (color.startsWith("rgb(") && color.endsWith(")")) {
            try {
                String[] rgb = color.substring(4, color.length() - 1).split(",");
                if (rgb.length == 3) {
                    int r = Integer.parseInt(rgb[0].trim());
                    int g = Integer.parseInt(rgb[1].trim());
                    int b = Integer.parseInt(rgb[2].trim());
                    return String.format("%02X%02X%02X", r, g, b);
                }
            } catch (NumberFormatException e) {
                // 忽略无效的RGB值
            }
        }

        // 处理RGBA颜色
        if (color.startsWith("rgba(") && color.endsWith(")")) {
            try {
                String[] rgba = color.substring(5, color.length() - 1).split(",");
                if (rgba.length == 4) {
                    int r = Integer.parseInt(rgba[0].trim());
                    int g = Integer.parseInt(rgba[1].trim());
                    int b = Integer.parseInt(rgba[2].trim());
                    return String.format("%02X%02X%02X", r, g, b);
                }
            } catch (NumberFormatException e) {
                // 忽略无效的RGBA值
            }
        }

        // 处理预定义的颜色名称
        Map<String, String> colorMap = new HashMap<>();
        colorMap.put("black", "000000");
        colorMap.put("white", "FFFFFF");
        colorMap.put("red", "FF0000");
        colorMap.put("green", "00FF00");
        colorMap.put("blue", "0000FF");
        colorMap.put("yellow", "FFFF00");
        colorMap.put("purple", "800080");
        colorMap.put("gray", "808080");
        colorMap.put("grey", "808080");
        colorMap.put("orange", "FFA500");
        colorMap.put("pink", "FFC0CB");
        colorMap.put("brown", "A52A2A");
        colorMap.put("cyan", "00FFFF");
        colorMap.put("magenta", "FF00FF");

        String hexColor = colorMap.get(color.toLowerCase());
        if (hexColor != null) {
            return hexColor;
        }

        // 如果无法解析颜色，返回默认黑色
        return "000000";
    }

    private static void applyParagraphStyles(XWPFParagraph paragraph, Element element, Map<String, XWPFStyle> styles) {
        String style = element.attr("style");

        // 如果当前元素没有样式，尝试获取父元素的样式
        if (style.trim().isEmpty()) {
            Node parent = element.parent();
            if (parent instanceof Element parentElement) {
                style = parentElement.attr("style");
            }
        }

        if (!style.trim().isEmpty()) {
            // 处理对齐方式
            String textAlign = extractStyleValue(style, "text-align");
            if (textAlign != null) {
                switch (textAlign) {
                    case "center":
                        paragraph.setAlignment(ParagraphAlignment.CENTER);
                        break;
                    case "right":
                        paragraph.setAlignment(ParagraphAlignment.RIGHT);
                        break;
                    case "justify":
                        paragraph.setAlignment(ParagraphAlignment.BOTH);
                        break;
                    default:
                        paragraph.setAlignment(ParagraphAlignment.LEFT);
                }
            }

            // 处理缩进
            String textIndent = extractStyleValue(style, "text-indent");
            if (textIndent != null) {
                try {
                    // 将em转换为pt (1em = 12pt)
                    if (textIndent.endsWith("em")) {
                        double emValue = Double.parseDouble(textIndent.replace("em", "").trim());
                        int ptValue = (int) (emValue * 12);
                        paragraph.setIndentationFirstLine(ptValue * 20);
                    } else {
                        int indent = Integer.parseInt(textIndent.replace("pt", "").trim());
                        paragraph.setIndentationFirstLine(indent * 20);
                    }
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                }
            }

            // 处理行高
            String lineHeight = extractStyleValue(style, "line-height");
            if (lineHeight != null) {
                double spacing = 1.0;
                if (lineHeight.endsWith("pt")) {
                    try {
                        double pt = Double.parseDouble(lineHeight.replace("pt", "").trim());
                        // 获取字号
                        String fontSize = extractStyleValue(style, "font-size");
                        double fontPt = 12.0; // 默认字号
                        if (fontSize != null && fontSize.endsWith("pt")) {
                            fontPt = Double.parseDouble(fontSize.replace("pt", "").trim());
                        }
                        if (fontPt > 0) {
                            spacing = pt / fontPt;
                        }
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                    }
                } else {
                    try {
                        spacing = Double.parseDouble(lineHeight);
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                    }
                }
                // 归一化到最近的0.5倍
                spacing = Math.round(spacing * 2) / 2.0;
                paragraph.setSpacingBetween(spacing, LineSpacingRule.AUTO);
            }
        }
    }

    private static String extractStyleValue(String style, String property) {
        if (style == null)
            return null;

        int start = style.indexOf(property + ":");
        if (start == -1)
            return null;

        start += property.length() + 1;
        int end = style.indexOf(";", start);
        if (end == -1)
            end = style.length();

        return style.substring(start, end).trim();
    }
}